import { arrayMoveMutable } from 'array-move'
export { debounce, throttle } from "throttle-debounce"
export { addListener, removeListener } from 'resize-detector'
export * from '@vinsurs/case-anything'
export { pLimit } from '@vinsurs/p-limit'
export function noop() {}
export function cloneDeep<T = any>(value: T): T {
  return JSON.parse(JSON.stringify(value))
}
export function closeCurrentWindow() {
  window.open('', '_self', '')
  window.close()
}
export function removeItem<T = Record<string, any>>(items: T[], predicate: ArrayPredicate<T>) {
  const index = items.findIndex(predicate)
  if (~index) {
    items.splice(index, 1)
  }
}
export function sortItem<T = Record<string, any>>(items: T[], predicate: ArrayPredicate<T>, type: 'up' | 'down') {
  const index = items.findIndex(predicate)
  const isFirst = index === 0
  const isLast = index === items.length - 1
  if (type === 'up') {
    if (isFirst)
      return
    const prevIndex = index - 1
    arrayMoveMutable(items, index, prevIndex)
  }
  else if (type === 'down') {
    if (isLast)
      return
    const nextIndex = index + 1
    arrayMoveMutable(items, index, nextIndex)
  }
}
export function mapToOptions<K extends string | number, V extends string>(map: Map<K,V>): Array<IOption<K>> {
  return Array.from(map).reduce((prev, [value, label], index) => {
    prev[index] = {
      value,
      label
    }
    return prev
  }, new Array<IOption<K>>(map.size))
}
export function isSetValue(value: unknown) {
  return typeof value !== 'undefined' && value !== null
}
export function getPopupContainer(triggerNode: HTMLElement) {
  return triggerNode.parentNode as any
}
export function hasOwn(object: object, key: PropertyKey): boolean {
  return Object.prototype.hasOwnProperty.call(object, key)
}
export function filterOption<V extends string | number | boolean = any>(input: string, option: IOption<V>) {
  return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0;
}